package com.example.toy.core.table;

import com.example.toy.core.commit.CommitMsg;
import com.example.toy.core.commit.ToyCommitView;
import com.example.toy.core.conf.ToyTableConfig;
import com.example.toy.core.fs.ToyTableFileView;
import com.example.toy.core.fs.ToyTableVersionFileView;
import com.example.toy.core.partition.PartitionPathStyle;
import com.example.toy.core.version.ToyVersion;
import java.lang.reflect.Constructor;
import java.util.Map;
import lombok.Getter;
import lombok.SneakyThrows;
import org.apache.avro.Schema;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;

@Getter
public abstract class ToyTableMeta {
  protected final ToyTable toyTable;

  /** 表存储路径 */
  protected final Path basePath;
  /** 版本 */
  protected final ToyVersion version;

  /** 表模式 */
  protected Schema schema;

  protected Schema partitionSchema;
  protected Schema keySchema;

  /** 配置项 */
  protected ToyTableConfig tableConfig;

  /** 当前版本下的文件列表视图 */
  protected ToyTableVersionFileView versionFileView;
  /** 当前表的文件列表视图 */
  protected ToyTableFileView realtimeFileView;

  /** 当前版本的提交信息 */
  protected CommitMsg commitMsg;

  /** 当前表的所有提交记录视图 */
  protected ToyCommitView commitView;

  /** 当前分区键到路径的映射 */
  protected Map<String, Path> partitionPathMap;

  protected PartitionPathStyle partitionPathStyle;

  public ToyTableMeta(ToyTable table, Path basePath, ToyVersion version) {
    this.toyTable = table;
    this.basePath = basePath;
    this.version = version;
  }

  public Configuration getHadoopConf() {
    return new Configuration();
  }

  public Path getDataDir() {
    return getTableConfig().getDataDir().orElse(this.basePath);
  }

  public String getTableName() {
    return getTableConfig().getTableName();
  }

  @SneakyThrows
  public synchronized PartitionPathStyle getPartitionPathStyle() {
    if (this.partitionPathStyle == null) {
      Class<PartitionPathStyle> partitionPathStyleClass =
          this.getTableConfig().getPartitionPathStyleClass();
      Constructor<PartitionPathStyle> constructor =
          partitionPathStyleClass.getConstructor(Path.class);
      this.partitionPathStyle = constructor.newInstance(this.getBasePath());
    }
    return this.partitionPathStyle;
  }
}
